package com.zsk.shop.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.base.page.BasePageFactory;
import com.zsk.shop.common.base.page.BasePageParams;
import com.zsk.shop.common.utils.*;
import com.zsk.shop.entity.ShopOrder;
import com.zsk.shop.entity.ShopOrderPoints;
import com.zsk.shop.entity.ShopOrderPointsDetail;
import com.zsk.shop.enums.EnumOrderPointsStatus;
import com.zsk.shop.enums.EnumOrderStatus;
import com.zsk.shop.enums.ServiceKeyTypeEnum;
import com.zsk.shop.mapper.ShopOrderPointsMapper;
import com.zsk.shop.model.params.OrderGoodsSnapshotParam;
import com.zsk.shop.model.params.OrderPointsGoodsSnapshot;
import com.zsk.shop.model.results.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author Ys
 * @date 2022年02月18日 10:18
 */
@Service
public class ShopOrderPointsService extends ServiceImpl<ShopOrderPointsMapper, ShopOrderPoints> {

    @Resource
    private ShopOrderPointsDetailService shopOrderPointsDetailService;
    @Resource
    private ShopUserService shopUserService;
    @Resource
    private UserAccountService userAccountService;
    @Resource
    private ShopOrderPointsService shopOrderPointsService;
    @Resource
    private ShopOrderService shopOrderService;

    /**
     * 添加积分列表
     *
     * @param shopOrder
     */
    public void saveShopOrderPoints(ShopOrder shopOrder) {
        if (ToolUtil.isEmpty(shopOrder.getReturnPoints()) || shopOrder.getReturnPoints() <= 0) {
            return;
        }
        for (int i = 0; i < shopOrder.getGoodsNumber(); i++) {
            OrderGoodsSnapshotParam snapshotParam = JSON.parseObject(shopOrder.getSnapshot(), OrderGoodsSnapshotParam.class);
            OrderPointsGoodsSnapshot snapshot = EntityConvertUtils.convertAToB(snapshotParam, OrderPointsGoodsSnapshot.class);
            snapshot.setCreateTime(shopOrder.getCreateTime());
            snapshot.setGoodsNumber(shopOrder.getGoodsNumber());
            ShopOrderPoints shopOrderPoints = ShopOrderPoints.builder()
                    .orderPointsNo(RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.ORDER_POINT_NO.getValue()))
                    .userNo(shopOrder.getUserNo())
                    .snapshotInfo(JSON.toJSONString(snapshot))
                    .sourceOrderNo(shopOrder.getOrderNo())
                    .useOrderNo("")
//                  .points((new BigDecimal(shopOrder.getReturnPoints())).multiply(new BigDecimal(shopOrder.getGoodsNumber())))
                    .points((new BigDecimal(shopOrder.getReturnPoints())))
                    .status(EnumOrderPointsStatus.WAIT.getCode())
                    .ratio(BigDecimal.ZERO)
                    .thawPoint(BigDecimal.ZERO)
                    .thawTotalPoint(BigDecimal.ZERO)
                    .thawMoney(BigDecimal.ZERO)
                    .isInvalid(false)
                    .createTime(new Date())
                    .build();
            this.save(shopOrderPoints);
        }
    }

    /**
     * 获取可抵用积分列表
     *
     * @param price
     * @param userNo
     * @return
     */
    public List<ShopOrderPoints> getMineShopOrderPointsList(BigDecimal price, String userNo) {
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getUserNo, userNo);
        queryWrapper.eq(ShopOrderPoints::getIsInvalid, false);
        queryWrapper.eq(ShopOrderPoints::getStatus, EnumOrderPointsStatus.SUCCESS.getCode());
        return list(queryWrapper);
    }

    /**
     * 获取当前积分状态
     * @param orderPointsNo
     * @return
     */
    public ShopOrderPoints getShopOrderPointsInfo(String orderPointsNo) {
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        queryWrapper.eq(ShopOrderPoints::getIsInvalid, false);
        queryWrapper.eq(ShopOrderPoints::getStatus, EnumOrderPointsStatus.SUCCESS.getCode());
        queryWrapper.last("limit 1");
        return getOne(queryWrapper);
    }

    public void updateOrderPoints(String orderPointsNo, String orderNo){
        LambdaUpdateWrapper<ShopOrderPoints> queryWrapper = new LambdaUpdateWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        queryWrapper.set(ShopOrderPoints::getStatus, EnumOrderPointsStatus.USE.getCode());
        queryWrapper.set(ShopOrderPoints::getUseTime, new Date());
        queryWrapper.set(ShopOrderPoints::getUseOrderNo, orderNo);
        update(queryWrapper);
    }

    /**
     * 获取用户总积分
     *
     * @param userNo
     * @return
     */
    public BigDecimal getTotalPoint(String userNo, String orderPointsNo) {
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getUserNo, userNo);
        if (ToolUtil.isNotEmpty(orderPointsNo)) {
            queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        }
        queryWrapper.eq(ShopOrderPoints::getIsInvalid, false);
        List<ShopOrderPoints> list = list(queryWrapper);
        BigDecimal total = list.stream().map(ShopOrderPoints::getPoints).reduce(BigDecimal.ZERO, BigDecimal::add);
        return total;
    }

    public BaseResponse<ShopUserPointDetailResult> shopUserPointDetail(String monthDay, String userNo, String pages, String limits) {
        ShopUserPointDetailResult result = EntityConvertUtils.convertAToB(shopUserService.queryByUserNo(userNo), ShopUserPointDetailResult.class);
        result.setUserBalance(userAccountService.getUserMoneyAccountNowBalance(userNo)
                .setScale(2, BigDecimal.ROUND_HALF_UP).toString());
        result.setUserPoint(shopOrderPointsService.getTotalPoint(result.getUserNo(), null));
        result.setUserThawTotalPoint(shopOrderPointsService.getTotalThrowPoint(result.getUserNo(), null));
        result.setUserThawWaitPoint(result.getUserPoint().add(result.getUserThawTotalPoint().multiply(new BigDecimal("-1"))));
        result.setCanUsePoint(shopOrderPointsService.getCanUsePoints(result.getUserNo(), null));
        Page pageContext = BasePageFactory.defaultPage(pages, limits);
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        if (ToolUtil.isNotEmpty(monthDay)) {
            Date startTime = DateUtils.getMonthStart(monthDay);
            Date endTime = DateUtils.getMonthEnd(monthDay);
            queryWrapper.and(x -> x.ge(ShopOrderPoints::getCreateTime, startTime)
                    .le(ShopOrderPoints::getCreateTime, endTime));
        }
        queryWrapper.eq(ShopOrderPoints::getUserNo, userNo);
        queryWrapper.orderByDesc(ShopOrderPoints::getCreateTime);
        IPage page = this.page(pageContext, queryWrapper);
        List<ShopOrderPoints> shopOrderPointsList = page.getRecords();
        List<ShopOrderPointsListResult> results = EntityConvertUtils.convertAListToBList(shopOrderPointsList, ShopOrderPointsListResult.class);
        for (ShopOrderPointsListResult pointsListResult : results) {

        }
        result.setUserPointList(results);
        return BaseResponse.success("用户积分明细列表", result, Integer.parseInt(page.getTotal() + ""));
    }

    private BigDecimal getTotalThrowPoint(String userNo, String orderPointsNo) {
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getUserNo, userNo);
        if (ToolUtil.isNotEmpty(orderPointsNo)) {
            queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        }
        queryWrapper.eq(ShopOrderPoints::getIsInvalid, false);
        List<ShopOrderPoints> list = list(queryWrapper);
        BigDecimal total = list.stream().map(ShopOrderPoints::getThawTotalPoint).reduce(BigDecimal.ZERO, BigDecimal::add);
        return total;
    }

    public BaseResponse<ShopOrderPointsDetailResult> shopOrderPointsDetailDetail(String orderPointsNo, String pages, String limits) {
        Page pageContext = BasePageFactory.defaultPage(pages, limits);
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        queryWrapper.last("limit 1");
        ShopOrderPointsDetailResult result = EntityConvertUtils.convertAToB(getOne(queryWrapper), ShopOrderPointsDetailResult.class);
        String useOrderNo = result.getUseOrderNo();
        if (ToolUtil.isNotEmpty(useOrderNo)) {
            ShopOrderInfoResult shopOrderInfoResult = shopOrderService.getOrderInfo(useOrderNo).getData();
            result.setBuyShopOrder(shopOrderInfoResult);
        }
        result.setThawPoint(shopOrderPointsService.getTotalPoint(result.getUserNo(), orderPointsNo));
        result.setCanUsePoints(shopOrderPointsService.getCanUsePoints(result.getUserNo(), orderPointsNo));
        result.setThawTotalPoint(shopOrderPointsService.getTotalThrowPoint(result.getUserNo(), orderPointsNo));
        result.setThawWaitPoint(result.getThawPoint().add(result.getThawTotalPoint().multiply(new BigDecimal("-1"))));
        LambdaQueryWrapper<ShopOrderPointsDetail> queryWrapper2 = new LambdaQueryWrapper<>();
        queryWrapper2.eq(ShopOrderPointsDetail::getOrderPointsNo, orderPointsNo);
        IPage page = shopOrderPointsDetailService.page(pageContext, queryWrapper2);
        List<ShopOrderPointsDetail> shopOrderPointsDetailList = page.getRecords();
        List<PointThawDetailResult> results = EntityConvertUtils.convertAListToBList(shopOrderPointsDetailList, PointThawDetailResult.class);
        for (PointThawDetailResult pointThawDetailResult : results) {
            BigDecimal point = result.getPoints();
            BigDecimal thawTotalPoint = point.multiply(pointThawDetailResult.getRatio());
            pointThawDetailResult.setThawTotalPoint(thawTotalPoint);
            //X积分->礼包
            pointThawDetailResult.setRatioToPoint(thawTotalPoint.multiply(pointThawDetailResult.getPointRatio()));
            //X积分->金额
            pointThawDetailResult.setRatioToMoney(thawTotalPoint.multiply(pointThawDetailResult.getMoneyRatio()));
        }
        result.setList(results);
        return BaseResponse.success("用户积分明细详情", result, Integer.parseInt(page.getTotal() + ""));
    }

    private BigDecimal getCanUsePoints(String userNo, String orderPointsNo) {
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getUserNo, userNo);
        queryWrapper.eq(ShopOrderPoints::getStatus, EnumOrderPointsStatus.SUCCESS.getCode());
        if (ToolUtil.isNotEmpty(orderPointsNo)) {
            queryWrapper.eq(ShopOrderPoints::getOrderPointsNo, orderPointsNo);
        }
        queryWrapper.eq(ShopOrderPoints::getIsInvalid, false);
        List<ShopOrderPoints> list = list(queryWrapper);
        BigDecimal total = list.stream().map(ShopOrderPoints::getPoints).reduce(BigDecimal.ZERO, BigDecimal::add);
        return total;
    }

    public List<ShopOrderPoints> listByUserNosWithNoThaw(List<String> userNoList) {
        if (ToolUtil.isEmpty(userNoList)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ShopOrderPoints::getUserNo, userNoList);
        queryWrapper.eq(ShopOrderPoints::getStatus, EnumOrderPointsStatus.WAIT.getCode());
        return this.list(queryWrapper);
    }

    public BaseResponse<List<ShopOrderPointsListResult>> shopUserCanUsePointList(BasePageParams params) {
        Page pageContext = BasePageFactory.defaultPage(params.getPage(), params.getLimit());
        LambdaQueryWrapper<ShopOrderPoints> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ShopOrderPoints::getUserNo, HttpContext.getUserNo());
        queryWrapper.ne(ShopOrderPoints::getStatus, EnumOrderPointsStatus.WAIT.getCode());
        queryWrapper.ne(ShopOrderPoints::getStatus, EnumOrderPointsStatus.DEFAULT.getCode());
        queryWrapper.orderByAsc(ShopOrderPoints::getStatus);
        queryWrapper.orderByDesc(ShopOrderPoints::getCreateTime);
        IPage page = this.page(pageContext, queryWrapper);
        List<ShopOrderPoints> shopOrderPointsList = page.getRecords();
        List<ShopOrderPointsListResult> results = EntityConvertUtils.convertAListToBList(shopOrderPointsList, ShopOrderPointsListResult.class);
        for (ShopOrderPointsListResult pointsListResult : results) {
            OrderPointsGoodsSnapshot snapshot = JSONObject.parseObject(pointsListResult.getSnapshotInfo(), OrderPointsGoodsSnapshot.class);
            pointsListResult.setVipLevel(ToolUtil.isEmpty(snapshot.getVipLevel()) ? 1 : snapshot.getVipLevel());
        }
        page.setRecords(results);
        return BasePageFactory.createPageInfo(page);
    }
}
